---
title: Render a prompt with steps
description: Learn how to render the steps of a prompt with the Latitude SDK
---

## Prompt

Chains and Steps are used to create multi-step prompts that can interact with the AI model in stages. Chains in PromptL allow you to break complex workflows into smaller, manageable steps. You can read more [about it here](/promptl/advanced/chains#chains-and-steps).

In this example, we use two steps. In the first step, we ask the model to think about the answer. Then, in the second step, we ask it to provide an explanation for why it chose that answer.

<CodeGroup>
```markdown example
---
provider: Latitude
model: gpt-4o-mini
temperature: 0.7
---

<step>
  You're a helpful assistant. Think about user question and provide the best answer.
  This is the question:
  {{ question }}
</step>

<step>
  Now that you have the best answer, please provide a detailed explanation of how you arrived at this answer.
</step>
```
</CodeGroup>

## Code

The key point to understand is that for each `<step>` found in the prompt, the SDK will invoke `onStep`. At that point, you can ask your LLM to provide a response.

<CodeGroup>
````typescript Typescript
import { Latitude, Adapters, Message } from '@latitude-data/sdk'
import OpenAI from 'openai'

async function run() {
  const sdk = new Latitude(process.env.LATITUDE_API_KEY, {
    projectId: Number(process.env.PROJECT_ID),
    versionUuid: 'live',
  })
  const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })

  const prompt = await sdk.prompts.get('render-chain/example')
  const result = await sdk.prompts.renderChain({
    prompt,
    parameters: { question: 'What is the meaning of life?' },
    adapter: Adapters.openai,
    onStep: async ({
      config,
      messages,
    }: {
      config: { [s: string]: unknown }
      messages: Message[]
    }) => {
      const response = await openai.chat.completions.create({
        model: config.model as string,
        temperature: config.temperature as number,
        messages,
      })

      return response.choices[0].message
    },
  })

  console.log('Result:', JSON.stringify(result, null, 2))
}

run()
````
````python Python
import asyncio
import os
from typing import Any, Dict, List, Sequence, Union

from devtools import pprint
from latitude_sdk import Latitude, LatitudeOptions, RenderChainOptions
from openai import AsyncOpenAI
from promptl_ai import Adapter, MessageLike


async def run():
    api_key = os.getenv("LATITUDE_API_KEY")
    sdk_options = LatitudeOptions(
        project_id=int(os.getenv("PROJECT_ID")),
        version_uuid="live",
    )
    sdk = Latitude(api_key, sdk_options)

    # Use oficial OpenAI SDK
    openai = AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY"))

    async def on_step(
        messages: List[MessageLike], config: Dict[str, Any]
    ) -> Union[str, MessageLike, Sequence[MessageLike]]:
        response = await openai.chat.completions.create(
            model=config["model"],
            temperature=config["temperature"],
            messages=[message.model_dump() for message in messages],
        )

        return response.choices[0].message.model_dump()

    prompt = await sdk.prompts.get("render-chain/example")

    # Here we render the chain and each step will be sent to OpenAI
    result = await sdk.prompts.render_chain(
        prompt,
        on_step,
        RenderChainOptions(
            parameters={"question": "What is the meaning of life?"},
            adapter=Adapter.OpenAI,
        ),
    )

    pprint(result)


asyncio.run(run())
````
</CodeGroup>
